package com.kla.power.util;

import com.kla.power.vo.CollectorVO;
import org.apache.commons.lang3.StringUtils;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

/**
 * 数据采集分析工具
 */
public class CollectorUtil {

    /**
     * 1.字节转成十六进制，获得采集器传来的所有数据
     * @param bytes
     * @return
     */
    public static String bytesToHexString (byte[] bytes) {
        StringBuilder sb = new StringBuilder ();
        for ( int i = 0; i < bytes.length; i++ ) {
            String hex = Integer.toHexString ( 0xFF & bytes[i] );
            if ( hex.length () == 1 ) {
                sb.append ( '0' );
            }
            sb.append ( hex );
        }
        return sb.toString ();
    }

    /**
     * 2.解析报文获得当前帧总的字节数
     * @param hex                     00 00 00 99 ...
     *                                通过解析前四个字节
     * @param collectorVO：要解析的下标和字节长度
     * @return
     */
    public static CollectorVO parseMessageToBytes (String hex, CollectorVO collectorVO) {
        long bytes = hexToDecimal ( hex, collectorVO.getStart (), collectorVO.getLength () );
        // 改变下次解析的起始下标
        collectorVO.setStart ( collectorVO.getLength () );
        collectorVO.setValue ( String.valueOf ( bytes ) );
        return collectorVO;
    }

    /**
     * 3.解析逆变器序列号的标识符，一个字节，该数后面的字节数为设备SN，但需要转UTF8
     * 00 00 01 03
     * 0e 31 30 30 30 30 30 30 30 30 30 33 31 35 38
     * f3
     * @param hex
     * @return
     */
    public static CollectorVO parseDeviceSnFlag (String hex, CollectorVO collectorVO) {
        long snFlag = hexToDecimal ( hex, collectorVO.getStart (), collectorVO.getLength () );
        collectorVO.setStart ( collectorVO.getStart () + collectorVO.getLength () );
        collectorVO.setValue ( String.valueOf ( snFlag ) );
        return collectorVO;
    }

    /**
     * 4.解析逆变器SN，通过前一个字节转十进制的长度，进行解析为UTF8编码
     * 00 00 01 03
     * 0e 31 30 30 30 30 30 30 30 30 30 33 31 35 38
     * f3
     * 04
     * @param hex：十六进制数据
     * @param collectorVO：要解析的操作对象
     * @return
     */
    public static CollectorVO parseDeviceSn (String hex, CollectorVO collectorVO) {
        String deviceSn = hexToUtf8 ( hex, collectorVO.getStart (), collectorVO.getLength () );
        collectorVO.setStart ( collectorVO.getStart () + collectorVO.getLength () );
        collectorVO.setValue ( deviceSn );
        return collectorVO;
    }

    /**
     * 5.解析实时数据上传标志，终端可以上传数据、可以下行数据，具体参考国网数据格式
     * 该部分要将十六进制转成二进制
     * @param hex
     * @param collectorVO
     * @return
     */
    public static CollectorVO parsePushFlag (String hex, CollectorVO collectorVO) {
        String binary = hexToBinary ( hex, collectorVO.getStart (), collectorVO.getLength () );
        collectorVO.setStart ( collectorVO.getStart () + collectorVO.getLength () );
        collectorVO.setValue ( binary );
        return collectorVO;
    }

    /**
     * 截取源数据，不解析
     * 6.解析上报实时数据
     * 十六进制:f3
     * 8.解析测点实时类型
     * 01(十六进制) - 实时上报
     * 02(十六进制) - 变位上报
     * @param hex
     * @param collectorVO
     * @return
     */
    public static CollectorVO parseHexData (String hex, CollectorVO collectorVO) {
        //只截取一个字节长度，不转换
        hex = hex.toUpperCase ().replace ( " ", "" );
        String substring = hex.substring ( collectorVO.getStart () * 2, collectorVO.getStart () * 2 + 2 * collectorVO.getLength () );
        collectorVO.setStart ( collectorVO.getStart () + collectorVO.getLength () );
        collectorVO.setValue ( substring );
        return collectorVO;
    }

    /**
     * 7.解析电站ID
     * @param hex
     * @param collectorVO
     * @return
     */
    public static CollectorVO parseStationId (String hex, CollectorVO collectorVO) {
        long stationId = hexToDecimal ( hex, collectorVO.getStart (), collectorVO.getLength () );
        collectorVO.setStart ( collectorVO.getStart () + collectorVO.getLength () );
        collectorVO.setValue ( String.valueOf ( stationId ) );
        return collectorVO;
    }

    /**
     * 通过字符串和指定长度截取子字符串
     * @param data:                      02 00 00 00 01 2f 84 00 01 00 01 04 28
     * @param index:开始截取的字节所在的下标，每个字节占两位
     * @param length：截取的字节长度
     * @return：返回截取成功后的子串
     */
    public static String parseData (String data, int index, int length) {
        if ( StringUtils.isBlank ( data ) ) {
            return null;
        }
        if ( data.length () < length ) {
            return null;
        }
        data = data.replace ( " ", "" ).trim ();
        String value = StringUtils.substring ( data, index * 2, index * 2 + length * 2 );
        return value;
    }


    /**
     * 5.获取时间戳
     * @param hex 00 00 02 99 00 f3 04 00 00 00 00 01 00 00 01 88 d7 d0 46 78
     *            从下标12开始截取8位，表示采集器传输的当前时间
     * @return
     */
    public static CollectorVO parseTimeStamp (String hex, CollectorVO collectorVO) {
        long timeStamp = hexToDecimal ( hex, collectorVO.getStart (), collectorVO.getLength () );
        collectorVO.setStart ( collectorVO.getStart () + collectorVO.getLength () );
        collectorVO.setValue ( String.valueOf ( timeStamp ) );
        return collectorVO;
    }


    /**
     * 5.根据源十六进制数获取采集的数据组数
     * @param hex
     * @return
     */
    public static CollectorVO parseGroupNumber (String hex, CollectorVO collectorVO) {
        long groupNum = hexToDecimal ( hex, collectorVO.getStart (), collectorVO.getLength () );
        collectorVO.setStart ( collectorVO.getStart () + collectorVO.getLength () );
        collectorVO.setValue ( String.valueOf ( groupNum ) );
        return collectorVO;
    }

    /**
     * 6.解析每组数据中的逆变器ID+测点ID
     * @param hex
     * @return
     */
    public static long parseInverterId (String hex, int start, int length) {
        return hexToDecimal ( hex, start, length );
    }

    /**
     * 解析每组数据最后一个字节，逆变器容量标识符，获取该数据对比报文文档
     * 46(十六进制) = 字符F，代表该逆变器容量是浮点型数
     * 'B'：byte - 42(十六进制)
     * 'S'：Short - 53(十六进制)
     * 'I' ：Int32 - 49(十六进制)
     * 'L'：Int64 - 4C(十六进制)
     * 'F'：float - 46(十六进制)
     * 'D'：double - 44(十六进制)
     * 'T'：(一字节长度+UTF-8文本) - 54(十六进制)
     * 'N'：empty (0字节) - 4E(十六进制)
     * @param hex
     * @param start：开始截取
     * @param length：截取长度
     * @return
     */
    public static String parseFlag (String hex, int start, int length) {
        hex = hex.replace ( " ", "" );
        String substring = hex.substring ( start * 2, start * 2 + 2 * length );
        return substring;
    }

    /**
     * 根据给定的十六进制求截取某一部分字节，将其转为十进制
     * @param: [hex] 00 00 01 03
     * 0e 31 30 30 30 30 30 30 30 30 30 33 31 35 38
     * 06 9B D9 49 01 3F 7D 70 A4 01 46 41 98 00 00
     * @param: start 开始截取的下标，从0开始
     * @param: length 截取的长度 0 表示不截取
     * @return: int
     * @description: 按位计算，位值乘权重
     */
    public static long hexToDecimal (String hex, int start, int length) {
        hex = hex.toUpperCase ();
        String trim = hex.replace ( " ", "" );
        if ( length > 0 ) {
            trim = trim.substring ( start * 2, start * 2 + 2 * length );
        }
        long outcome = 0;
        for ( int i = 0; i < trim.length (); i++ ) {
            char hexChar = trim.charAt ( i );
            outcome = outcome * 16 + charToDecimal ( hexChar );
        }
        return outcome;
    }

    /**
     * @param: [c]
     * @return: int
     * @description:将字符转化为数字
     */
    private static int charToDecimal (char c) {
        if ( c >= 'A' && c <= 'F' )
            return 10 + c - 'A';
        else
            return c - '0';
    }


    /**
     * 十六进制转Float类型
     * @param hex
     * @param start
     * @param length
     * @return
     */
    public static float hexToFloat (String hex, int start, int length) {
        hex = hex.toUpperCase ();
        hex = hex.replace ( " ", "" );
        if ( length > 0 ) {
            hex = hex.substring ( start * 2, start * 2 + 2 * length );
        }
        Long l = Long.parseLong ( hex, 16 );
        Float f = Float.intBitsToFloat ( l.intValue () );
        return f;
    }

    /**
     * 十六进制转double类型
     * @param hex
     * @param start
     * @param length
     * @return
     */
    public static double hexToDouble (String hex, int start, int length) {
        hex = hex.toUpperCase ();
        hex = hex.replace ( " ", "" );
        if ( length > 0 ) {
            hex = hex.substring ( start * 2, start * 2 + 2 * length );
        }
        Long l = Long.parseLong ( hex, 16 );
        double v = Double.longBitsToDouble ( l );
        return v;
    }


    /**
     * 十六进制转成utf-8
     * @param hex
     * @param start
     * @param length
     * @return
     */
    public static String hexToUtf8 (String hex, int start, int length) {
        hex = hex.replace ( " ", "" );
        if ( length > 0 ) {
            hex = hex.substring ( start * 2, start * 2 + 2 * length );
        }
        StringBuilder builder = new StringBuilder ();
        for ( int i = 0; i < hex.length (); i += 2 ) {
            String substring = hex.substring ( i, i + 2 );
            int codePoint = Integer.parseInt ( substring, 16 );
            builder.appendCodePoint ( codePoint );
        }
        String result = builder.toString ().trim ();
        return result;
    }

    /**
     * 将字符串转成十六进制数据
     * @param utf8Str
     * @return
     */
    public static String utf8ToHex (String utf8Str) {
        if ( utf8Str == null ) {
            return null;
        }
        // 将字符串转换为字节数组
        byte[] bytes = utf8Str.getBytes ( StandardCharsets.UTF_8 );
        // 创建一个StringBuilder来构建16进制字符串
        StringBuilder hexStrBuilder = new StringBuilder ( bytes.length * 2 );
        // 遍历字节数组，将每个字节转换为16进制字符串并添加到StringBuilder中
        for ( byte b : bytes ) {
            hexStrBuilder.append ( String.format ( "%02X", b ) );
        }
        return hexStrBuilder.toString ();
    }

    /**
     * 将16进制转换为二进制
     * @param hex
     * @param start
     * @param length
     * @return
     */
    public static String hexToBinary (String hex, int start, int length) {
        hex = hex.replace ( " ", "" );
        if ( length > 0 ) {
            hex = hex.substring ( start * 2, start * 2 + 2 * length );
        }
        //16进制转10进制
        BigInteger sInt = new BigInteger ( hex, 16 );
        //10进制转2进制
        String result = sInt.toString ( 2 );
        //字符串反转
        return new StringBuilder ( result ).toString ();
    }


}
